﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;

namespace Microsoft.Samples
{
    public static class FullScreenHelper
    {  
        public static void GoFullscreen(this Window window)  
        {      
            // Make window borderless      
            window.WindowStyle = WindowStyle.None;      
            window.ResizeMode = ResizeMode.NoResize;      
            
            // Get handle for nearest monitor to this window      
            WindowInteropHelper wih = new WindowInteropHelper(window);      
            IntPtr hMonitor = MonitorFromWindow(wih.Handle, MONITOR_DEFAULTTONEAREST);      
            // Get monitor info      
            MONITORINFOEX monitorInfo = new MONITORINFOEX();    
            monitorInfo.cbSize = Marshal.SizeOf(monitorInfo);     
            GetMonitorInfo(new HandleRef(window, hMonitor), monitorInfo);    

            // Create working area dimensions, converted to DPI-independent values  
            HwndSource source = HwndSource.FromHwnd(wih.Handle);    
            if (source == null) return; 
            // Should never be null     
            if (source.CompositionTarget == null) 
                return; 

            // Should never be null     
            Matrix matrix = source.CompositionTarget.TransformFromDevice;    
            RECT workingArea = monitorInfo.rcMonitor;    
            Point dpiIndependentSize =       
                matrix.Transform(         
                new Point(            
                    workingArea.Right - workingArea.Left,  
                    workingArea.Bottom - workingArea.Top));   
            // Maximize the window to the device-independent working area ie   
            // the area without the taskbar.    
            // NOTE - window state must be set to Maximized as this adds certain  
            // maximized behaviors eg you can't move a window while it is maximized, 
            // such as by calling Window.DragMove     
            window.MaxWidth = dpiIndependentSize.X;    
            window.MaxHeight = dpiIndependentSize.Y;     
            window.WindowState = WindowState.Maximized;
        }  
        
        // Nearest monitor to window  
        const int MONITOR_DEFAULTTONEAREST = 2; 
        // To get a handle to the specified monitor  
        [DllImport("user32.dll")]  
        static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags); 
        // To get the working area of the specified monitor 
        [DllImport("user32.dll")] 
        public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX monitorInfo);  
        
        // Rectangle (used by MONITORINFOEX)  
        [StructLayout(LayoutKind.Sequential)]  
        public struct RECT 
        {     
            public int Left;   
            public int Top;     
            public int Right;     
            public int Bottom;  
        } 
        
        // Monitor information (used by GetMonitorInfo()) 
        [StructLayout(LayoutKind.Sequential)]  
        public class MONITORINFOEX  
        {   
            public int cbSize;  
            public RECT rcMonitor;
            // Total area   
            public RECT rcWork;
            // Working area  
            public int dwFlags;  
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]     
            public char[] szDevice;
        }
    }
}
